<?php

class request implements Observable
{
   private $langs          = array();
   private $currentLang    = array();
   private $defaultLang    = array();
   private $tags           = NULL;
   private $contentTypes   = NULL;
   private $filters        = NULL;
   private $order          = NULL;
   private $page           = 1;
   private $path           = array();
   private $adminMode      = FALSE;
   private $observers      = array();
   private $secure         = false;
   private $request_method = NULL;
   private $request_data   = array('post' => NULL, 'get' => NULL, 'files' => NULL);

   /**
    * Parse REQUEST_URI
    */
   protected function  __construct()
   {
      if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {
         $this->secure = true;
      }
      
      $this->request_method = $_SERVER['REQUEST_METHOD'];
      if(!empty($_POST)) $this->request_data['post'] = $_POST;
      if(!empty($_GET))  $this->request_data['get']  = $_GET;
      $this->get_FILES();

      $request_uri = $_SERVER['REQUEST_URI'];
      $request_uri = explode('?', $request_uri);
      $request_uri = explode('/', $request_uri[0]);

      for($i=0, $t=sizeof($request_uri); $i<$t; $i++)
      {
         $value = $request_uri[$i];
         $value = urldecode($value);
         $p = strrpos($value, '.');
         if($p !== FALSE)
         {
            $value = substr($value, 0, $p);
         }
         $value = strip_tags($value);
         $value = stripslashes($value);
         $value = trim($value);
         $value = mb_strtolower($value, 'UTF-8');

         # check if TAG
         $p = strpos($value, 'tag:');
         if($p !== FALSE)
         {
            $this->tags = str_replace('tag:', '', $value);
            continue;
         }

         # check if TYPE
         $p = strpos($value, 'type:');
         if($p !== FALSE)
         {
            $value = str_replace('type:', '', $value);
            $_K = kernel::getInstance();
            $types = $_K->getTypes('a');
            if(isset($types[$value]))
            {
               $this->contentTypes = $value;
            } else
            {
               $v = array_search($value, $types);
               if($v !== FALSE)
               {
                  $this->contentTypes = $v;
               }
            }
            continue;
         }

         # check if ORDER
         $p = strpos($value, 'order:');
         if($p !== FALSE)
         {
            $this->order = str_replace('order:', '', $value);
            continue;
         }
         
         
         # check if Filter by Field
         $p = strpos($value, 'filter:');
         if($p !== FALSE)
         {
            $value = str_replace('filter:', '', $value);
            $value = explode(',', $value);
            for($i=0, $t=sizeof($value); $i<$t; $i++)
            {
               if(preg_match('/^[a-z]+:\d+$/i', $value[$i]))
               {
                  $f = explode(':', $value[$i]);
                  $this->filters[$f[0]] = $f[1];
               }
            }
            continue;
         }


         # check if PAGE
         if(preg_match('/^page(\d+)$/i', $value, $match))
         {
            $this->page = $match[1] < 1844674407370955163 ? (int)$match[1] : 1;

            continue;
         }
         

         $value = preg_replace('/!(\w-_)/', '', $value);
         if($value == '' || preg_match('/^([.]{1,})$/i', $value)) continue;

         $this->path[] = $value;
      }

      if(!empty($this->path[0]) && $this->path[0] == 'admin')
      {
         $this->adminMode = TRUE;
         config::getInstance()->notify(signs::S_MODE_ADMIN);
      }

      $this->loadLangs();
   }
   
   
   
   private function get_FILES()
   {
      $files = array();
      if(!empty($_FILES))
      {
         foreach($_FILES AS $n => $file)
         {
            $files[$n] = array();
            if($this->reversFilesArray('tmp_name', $file['tmp_name'], $files[$n]))
            {
               $this->reversFilesArray('name', $file['name'], $files[$n]);
               $this->reversFilesArray('type', $file['type'], $files[$n]);
               $this->reversFilesArray('error', $file['error'], $files[$n]);
               $this->reversFilesArray('size', $file['size'], $files[$n]);
            } else
            {
               unset($files[$n]);
            }
         }
      }
      
      $this->request_data['files'] = $files;
   }
   
   
   private function reversFilesArray($param, $input, &$output)
   {
      if(is_array($input))
      {
         list($key, $val) = each($input);
         if(!isset($output[$key])) $output[$key] = array();
         return $this->reversFilesArray($param, $val, $output[$key]);
      } else
      {
         $output[$param] = $input;
         if($param == 'tmp_name') return is_uploaded_file ($input);
      }
      
      return false;
   }




   public function addObserver(Observer $observer)
   {
      $i = array_search($observer, $this->observers);
      if($i === FALSE)
         $this->observers[] = $observer;
   }
   
   public function removeObserver(Observer $observer)
   {
      $i = array_search($observer, $this->observers);
      if($i !== FALSE)
         unset($this->observers[$i]);
   }
   
   public function fireEvent($msg = NULL)
   {
      echo 'admin 2 '. sizeof($this->observers) ; exit();
      if(!empty($this->observers))
      {
         foreach($this->observers AS $observer)
         {
            $observer->notify($msg);
         }
      }
   }

      /**
    * Loading languages
    */
   private function loadLangs()
   {
      $DB = database::getInstance();
      $DB->sql = 'SELECT * FROM meccano_langs WHERE `active` = "1" ORDER BY position';
      $DB->DB_Fetch();

      for($i=0, $t=$DB->rows; $i<$t; $i++)
      {
         $this->langs[$DB->fetched[$i]['alias']] = $DB->fetched[$i];
      }

      # SET DEFAULT LANGS VALUES
      $tmp = reset($this->langs);
      $this->defaultLang = array($tmp['id'] => $tmp['alias']);
      $this->currentLang = array($tmp['id'] => $tmp['alias']);

      # REMOVE FROM REQUEST PATH LANG POINTER
      if(!empty($this->path) && isset($this->langs[$this->path[0]]))
      {
         $l = array_shift($this->path);
         $this->currentLang = array($this->langs[$l]['id'] => $l);
      }

      if(config::read('langs_domain'))
      {
         $domain = str_replace('www.', '', $_SERVER['HTTP_HOST']);
         foreach($this->langs AS $l)
         {
            if($l['domain'] == $domain)
            {
               $this->currentLang = array($l['id'] => $l['alias']);
               break;
            }
         }
      }

      $url       = !empty($this->path) ? implode('/', $this->path) : '';
      $extention = config::read('url_extention') ? config::read('url_extention') : 'html';
      foreach ($this->langs AS &$l)
      {
         $url_base  = config::read('langs_domain') ? 'http://'. $l['domain'] .'/' : ($l['id'] != $this->getLangDefaultId() ? '/'. $l['alias'] .'/' : '/');
         $url_trail = !empty($url) ? '/' : '';

         $l['baseurl'] = $url_base;
         $l['url']     = $url_base . $url . $url_trail;
         $l['href']    = $url_base . $url . (empty($url_trail) ? 'index' : '') .'.'. $extention;
      }
      unset($l);
   }


   /**
    * Get All active Languages
    *
    * @return array
    */
   public function getLangAll()
   {
      $langs = array();
      foreach($this->langs AS $l)
      {
         if($l['active']) $langs[$l['alias']] = $l;
      }
      return $langs;
   }


   /**
    * Get IDs of all active languages
    *
    * @return array
    */
   public function getLangAllId()
   {
      $langs = $this->getLangAll();
      if(!empty($langs))
      {
         $tmp = array();
         foreach($langs AS $l)
         {
            $tmp[] = $l['id'];
         }
         $langs = $tmp;
      }

      return $langs;
   }

   public function getLangDefaultId()
   {
      return key($this->defaultLang);
   }

   public function getLangDefaultAlias()
   {
      return reset($this->defaultLang);
   }

   public function getLangDefault()
   {
      $alias = $this->getLangDefaultAlias();
      return $this->langs[$alias];
   }

   public function getLangCurrentId()
   {
      return key($this->currentLang);
   }

   public function getLangCurrentAlias()
   {
      return reset($this->currentLang);
   }

   public function getLangCurrent()
   {
      $alias = $this->getLangCurrentAlias();
      return $this->langs[$alias];
   }

   public function getLangData($alias)
   {
      $lang = NULL;
      foreach($this->langs AS $l)
      {
         if($l['id'] == $alias || $l['alias'] == $alias)
         {
            $lang = $l;
            break;
         }
      }

      if(empty($lang))
      {
         $default = $this->getLangDefaultAlias();
         $lang = $this->langs[$default];
      }

      return $lang;
   }

   public function getRequestPath($i = NULL)
   {
      if(is_numeric($i))
      {
         if(isset($this->path[$i]))
         {
            return $this->path[$i];
         }
         
         return FALSE;
      }
      
      return $this->path;
   }

   public function getRequestLength()
   {
      return (sizeof($this->path) - 1);
   }

   public function getRequestLast()
   {
      $e = end($this->path);
      reset($this->path);
      return $e;
   }

   public function getRequestPage()
   {
      return $this->page;
   }

   public function getRequestTags()
   {
      return $this->tags;
   }

   public function getRequestContentTypes()
   {
      return $this->contentTypes;
   }

   public function getRequestOrder()
   {
      return $this->order;
   }
   
   public function getRequestFilters()
   {
      return $this->filters;
   }

   public function isAdminMode()
   {
      return $this->adminMode;
   }
   
   public function isPost()
   {
      if($this->request_method == 'POST') return TRUE;
   }
   
   public function isGet()
   {
      if($this->request_method == 'GET') return TRUE;
   }

   public static function getInstance()
   {
      static $db_object;
      if(!is_object($db_object))
      {
         $db_object = new request();
      }
      return $db_object;
   }

   public static function getRequest($type = 'path', $params = NULL)
   {
      $_this  = request::getInstance();
      $method = 'getRequest'. mb_strtoupper(substr($type, 0, 1), 'UTF-8') . substr($type, 1);
      if(method_exists($_this, $method))
      {
         return $_this->{$method}($params);
      }
      return FALSE;
   }

   public static function getLang($type = 'all', $params = NULL)
   {
      $_this = request::getInstance();
      $method = 'getLang'. mb_strtoupper(substr($type, 0, 1), 'UTF-8') . substr($type, 1);
      if(method_exists($_this, $method))
      {
         return $_this->{$method}($params);
      }
      return FALSE;
   }
   
   public static function adminMode()
   {
      $_this = request::getInstance();
      return $_this->isAdminMode();
   }
   
   public function dataGet($name)
   {
      if(isset($this->request_data['get'][$name]))
         return $this->request_data['get'][$name];
      
      return NULL;
   }
   
   public function dataPost($name)
   {
      if(isset($this->request_data['post'][$name]))
         return $this->request_data['post'][$name];
      
      return NULL;
   }
   
   public function dataFiles($name)
   {
      if(isset($this->request_data['files'][$name]))
         return $this->request_data['files'][$name];
      
      return NULL;
   }
   
   public function data($name)
   {
      $data = self::dataGet($name);

      if($data === NULL) $data = self::dataPost($name);
      elseif(self::dataPost($name) !== NULL) $data = array_merge((array)$data, (array)self::dataPost($name));

      if($data === NULL) $data = self::dataFiles($name);
      elseif(self::dataFiles($name) !== NULL) $data = array_merge((array)$data, (array)self::dataFiles($name));

      return $data;
   }
}